package com.edfu.core.coursemgt.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.edfu.core.coursemgt.persistence.entity.CourseEntity;
import com.edfu.core.coursemgt.persistence.entity.CourseOfferingEntity;
import com.edfu.core.coursemgt.persistence.entity.CourseOfferingInstanceEntity;
import com.edfu.core.coursemgt.persistence.entity.LessonEntity;
import com.edfu.core.coursemgt.persistence.entity.LessonUnitEntity;
import com.edfu.core.coursemgt.vo.Course;
import com.edfu.core.coursemgt.vo.CourseOffering;
import com.edfu.core.coursemgt.vo.CourseOfferingInstance;
import com.edfu.core.coursemgt.vo.Lesson;
import com.edfu.core.coursemgt.vo.LessonUnit;
import com.edfu.core.identitymgt.persistence.entity.UserEntity;
import com.edfu.core.institutemgt.persistence.entity.AcadSemEntity;
import com.edfu.core.institutemgt.persistence.entity.BatchEntity;
import com.edfu.core.institutemgt.persistence.entity.BranchEntity;
import com.edfu.core.institutemgt.persistence.entity.InstituteEntity;
import com.edfu.core.institutemgt.persistence.entity.SectionEntity;
import com.edfu.core.institutemgt.vo.AcademicSemester;
import com.edfu.core.institutemgt.vo.Batch;
import com.edfu.core.institutemgt.vo.Branch;
import com.edfu.core.institutemgt.vo.Institute;
import com.edfu.core.institutemgt.vo.Section;

public class CourseMgtModelConverter {
	
	public static InstituteEntity getInstituteEntity(Institute from) {
		InstituteEntity to = new InstituteEntity();
		to.setCode(from.getCode());
		to.setAddressLine1(from.getAddressLine1());
		to.setAddressLine2(from.getAddressLine2());
		to.setAddressLine3(from.getAddressLine3());
		to.setCity(from.getCity());
		to.setState(from.getState());
		to.setCountry(from.getCountry());
		to.setMobile(from.getMobile());
		to.setPhone1(from.getPhone1());
		to.setPhone2(from.getPhone2());
		to.setWebsite(from.getWebsite());
		return to;
	}
	
	public static Institute getInstituteVO(InstituteEntity from) {
		Institute to = new Institute();
		to.setCode(from.getCode());
		to.setAddressLine1(from.getAddressLine1());
		to.setAddressLine2(from.getAddressLine2());
		to.setAddressLine3(from.getAddressLine3());
		to.setCity(from.getCity());
		to.setState(from.getState());
		to.setCountry(from.getCountry());
		to.setMobile(from.getMobile());
		to.setPhone1(from.getPhone1());
		to.setPhone2(from.getPhone2());
		to.setWebsite(from.getWebsite());
		return to;
	}
	
	public static BranchEntity getBranchEntity(Branch bvo) {
		BranchEntity be = new BranchEntity();
		be.setCode(bvo.getCode());
		be.setDescription(bvo.getDescription());
		if ( bvo.getInstitute() != null )
			be.setInstitute(getInstituteEntity(bvo.getInstitute()));
		be.setTitle(bvo.getTitle());
		if ( bvo.getParentBranch() != null )
			be.setParentBranch(getParentBranchEntity(bvo.getParentBranch()));
		return be;
	}
	
	private static BranchEntity getParentBranchEntity(Branch pbvo) {
		BranchEntity pbe = new BranchEntity();
		pbe.setCode(pbvo.getCode());
		return pbe;
	}
	
	public static BatchEntity getBatchEntity(Batch from) {
		BatchEntity to = new BatchEntity();
		to.setCode(from.getCode());
		to.setDescription(from.getDescription());
		to.setTitle(from.getTitle());
		//to.setBranch(getBranchEntity(from.getBranch()));
		
//		if ( from.getSections() != null && from.getSections().size() > 0) {
//			Set<SectionEntity> sections = new HashSet<SectionEntity>();
//			for ( Section section : from.getSections() ) {
//				SectionEntity sectionEntity = getSectionEntity(section); 
//				sectionEntity.setBatch(to);
//				sections.add(sectionEntity);
//			}
//			to.setSections(sections);
//		}
		return to;
	}
	
	public static SectionEntity getSectionEntity(Section from) {
		SectionEntity to = new SectionEntity();
		to.setCode(from.getCode());
		to.setDescription(from.getDescription());
		return to;
	}
	
	public static AcademicSemester getSemester(AcadSemEntity from) {
		AcademicSemester to = new AcademicSemester();
		to.setName(from.getName());
		to.setDescription(from.getDescription());
		to.setCode(from.getCode());
		return to;
	}
	
	public static AcadSemEntity getSemesterEntity(AcademicSemester from) {
		AcadSemEntity to = new AcadSemEntity();
		to.setName(from.getName());
		to.setDescription(from.getDescription());
		to.setCode(from.getCode());
		return to;
	}
	
	public static CourseEntity getCourseEntity(Course from) {
		CourseEntity to = new CourseEntity();
		to.setCode(from.getCode());
		to.setCourseCurriculum(from.getCourseCurriculum());
		to.setDescription(from.getDescription());
		to.setName(from.getName());
		return to;
	}
	
	public static Course getCourse(CourseEntity from) {
		Course to = new Course();
//		to.setCategoryName(from.getCategory().getName());
		to.setCode(from.getCode());
		to.setCourseCurriculum(from.getCourseCurriculum());
		to.setCreatedOn(from.getCreatedOn());
		to.setDescription(from.getDescription());
		to.setName(from.getName());
//		to.setTest(from.get);
		
		return to;
	}
	
	public static CourseOfferingEntity getCourseOfferingEntity(CourseOffering from) {
		CourseOfferingEntity to = new CourseOfferingEntity();
		to.setCode(from.getCode());
		to.setDescription(from.getDescription());
		to.setLanguage(from.getLanguage());
		to.setPrice(from.getPrice());
		to.setFree(from.isFree());
		to.setMode(from.getMode());
		to.setVisibility(from.getVisibility());
		to.setState(from.getState());
		to.setTitle(from.getTitle());
		if ( from.getLessons() != null && from.getLessons().size() > 0 ) {
			Set<LessonEntity> lessonEntitiesSet = new HashSet<LessonEntity>();
			for ( Lesson lesson : from.getLessons()) {
				LessonEntity lessonEntity = getLessonEntity(lesson);
				lessonEntitiesSet.add(lessonEntity);
			}
			to.setLessons(lessonEntitiesSet);
		}

		return to;
	}
	
	public static CourseOffering getCourseOffering(CourseOfferingEntity from) {
		CourseOffering to = new CourseOffering();
		to.setCode(from.getCode());
		to.setDescription(from.getDescription());
		to.setLanguage(from.getLanguage());
		to.setPrice(from.getPrice());
		to.setFree(from.isFree());
		to.setMode(from.getMode());
		to.setVisibility(from.getVisibility());
		to.setState(from.getState());
		to.setTitle(from.getTitle());
		if(from.getLessons() != null && from.getLessons().size() > 0)  {
			Set<Lesson> lessons = new HashSet<Lesson>();
			for (LessonEntity le : from.getLessons()) {
				lessons.add(getLesson(le));
			}
			to.setLessons(lessons);
		}
		
		return to;
	}
	
	public static LessonEntity getLessonEntity(Lesson from) {
		LessonEntity to = new LessonEntity();
		to.setContentDirectory(from.getContentDirectory());
		to.setDescription(from.getDescription());
		to.setLanguage(from.getLanguage());
		to.setPrice(from.getPrice());
		to.setPublished(from.isPublished());
		to.setTitle(from.getTitle());
		to.setLessonNo(from.getLessonNo());
		to.setAuthor(_getUserEntity(from.getAuthor()));
		to.setName(from.getName());
		if ( from.getUnits() != null && from.getUnits().size() > 0) {
			List<LessonUnitEntity> unitEntitiesList = new ArrayList<LessonUnitEntity>();
			for ( LessonUnit unit : from.getUnits() ) {
				unitEntitiesList.add(getLessonUnitEntity(unit, to));
				//Each unit can have multiple sub-units 
				List<LessonUnit>  childUnitsList = new ArrayList<LessonUnit>();
				childUnitsList = _getChildUnits(unit, childUnitsList);
				if (childUnitsList != null && childUnitsList.size()>0) {
					for (LessonUnit childUnit : childUnitsList) {
						unitEntitiesList.add(getLessonUnitEntity(childUnit, to));
					}
				}
			}
			to.setUnits(unitEntitiesList);
		}
		return to;
	}
	
	public static Lesson getLesson(LessonEntity from) {
		Lesson to = new Lesson();
		to.setContentDirectory(from.getContentDirectory());
		to.setDescription(from.getDescription());
		to.setLanguage(from.getLanguage());
		to.setPrice(from.getPrice());
		to.setPublished(from.isPublished());
		to.setTitle(from.getTitle());
		to.setLessonNo(from.getLessonNo());
		to.setAuthor(from.getAuthor().getUserId());
		to.setName(from.getName());
		if(from.getUnits() != null && from.getUnits().size() > 0) {
			List<LessonUnit> unitsList = new ArrayList<LessonUnit>();
			for ( LessonUnitEntity unitEnt : from.getUnits() ) {
				unitsList.add(getLessonUnitShallow(unitEnt));
			}
			to.setUnits(_getHierarchicalList(unitsList));
		}
		return to;
	}
	
	public static LessonUnitEntity getLessonUnitEntity(LessonUnit from, LessonEntity lesson) {
		LessonUnitEntity to = new LessonUnitEntity();
		to.setName(from.getName());
		to.setTitle(from.getTitle());
		to.setUnitNo(from.getUnitNo());
		to.setLesson(lesson);
		if ( from.getParentUnitName() != null && from.getParentUnitName().trim().length() > 0) {
			LessonUnitEntity parentUnit = new LessonUnitEntity();
			parentUnit.setName(from.getParentUnitName());
		}
		return to;
	}
	
	public static LessonUnitEntity getLessonUnitEntity(LessonUnit from) {
		LessonUnitEntity to = new LessonUnitEntity();
		to.setName(from.getName());
		to.setTitle(from.getTitle());
		to.setUnitNo(from.getUnitNo());
		if ( from.getParentUnitName() != null && from.getParentUnitName().trim().length() > 0 ) {
			LessonUnitEntity parentUnit = new LessonUnitEntity();
			parentUnit.setName(from.getParentUnitName());
		}
		return to;
	}
	
	public static LessonUnit getLessonUnitShallow(LessonUnitEntity from) {
		LessonUnit to = new LessonUnit();
		to.setName(from.getName());
		to.setTitle(from.getTitle());
		to.setUnitNo(from.getUnitNo());
		if(from.getParentUnit() != null) {
			to.setParentUnitName(from.getParentUnit().getName());
		}
		return to;
	}
	
	public static LessonUnit getLessonUnit(LessonUnitEntity from) {
		LessonUnit to = getLessonUnitShallow(from);
		to.setContentDirectory(from.getContentDirectory());
		return to;
	}
	
	
	public static CourseOfferingInstanceEntity getCourseOfferingInstanceEntity(CourseOfferingInstance from) {
		CourseOfferingInstanceEntity to = new CourseOfferingInstanceEntity();
		to.setSubscribe(from.isSubscribe());
		to.setUnsubscribe(from.isUnsubscribe());
		to.setStatus(from.getStatus());
		return to;
	}
	
	public static CourseOfferingInstance getCourseOfferingInstance(CourseOfferingInstanceEntity from) {
		CourseOfferingInstance to = new CourseOfferingInstance();
		to.setSubscribe(from.isSubscribe());
		to.setUnsubscribe(from.isUnsubscribe());
		to.setStatus(from.getStatus());
		to.setCourseOfferingCode(from.getCourseOffering().getCode());
		to.setOwnerUserId(from.getOwner().getUserId());
		return to;
	}
	
	private static List<LessonUnit> _getChildUnits(LessonUnit unit, List<LessonUnit> currentUnitsList) {
		if ( unit.getChildUnits() != null && unit.getChildUnits().size() > 0 ) {
			for ( LessonUnit childUnit : unit.getChildUnits() ) {
				currentUnitsList.add(childUnit);
				_getChildUnits(childUnit, currentUnitsList);
			}
		}
		return currentUnitsList;
	}
	
	private static UserEntity _getUserEntity(String userId) {
		UserEntity to = new UserEntity();
		to.setUserId(userId);
		return to;
	}
	
	public static List<LessonUnit> _getHierarchicalList(List<LessonUnit> flatList){
		List<LessonUnit> result = new ArrayList<LessonUnit>();
		Map<String, LessonUnit> map = new HashMap<String, LessonUnit>();
		for(LessonUnit lu: flatList)
			map.put(lu.getName(), lu);
				
		for(LessonUnit lessonUnit: flatList){
			if(lessonUnit.getParentUnitName() == null || lessonUnit.getParentUnitName().isEmpty())
				result.add(lessonUnit);
			else{
				List<LessonUnit> childUnits = map.get(lessonUnit.getParentUnitName()).getChildUnits();
				if(childUnits == null || childUnits.size() ==  0){
					childUnits = new ArrayList<LessonUnit>();
					childUnits.add(lessonUnit);
					map.get(lessonUnit.getParentUnitName()).setChildUnits(childUnits);
				}
				else{
					childUnits = map.get(lessonUnit.getParentUnitName()).getChildUnits();
					childUnits.add(lessonUnit);
					map.get(lessonUnit.getParentUnitName()).setChildUnits(childUnits);
				}
			}
		}
		return result;
	}
	
	public static void _printHList(List<LessonUnit> list, String str){
		if(list == null)
			return;
		for(LessonUnit lu: list){
			System.out.println(str + lu.getName());
			_printHList(lu.getChildUnits(), str+"*");
		}
	}

	
	
}
